import matplotlib.pyplot as plt
import numpy as np
import math

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

def calculate_pi_approximation(n_sides):
    """使用正n边形逼近π"""
    # 假设圆半径为1，计算内接正n边形的周长的一半（对应π的近似值）
    central_angle = 2 * math.pi / n_sides
    side_length = 2 * math.sin(central_angle / 2)
    perimeter = n_sides * side_length
    return perimeter / 2  # 因为周长=2πr，r=1，所以π≈周长/2

# 计算不同边数下的π近似值
side_numbers = [4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 256, 512, 1024]
pi_approximations = []

for n in side_numbers:
    pi_approx = calculate_pi_approximation(n)
    pi_approximations.append(pi_approx)

# 绘制结果
plt.figure(figsize=(14, 10))

# 子图1：π的逼近过程
plt.subplot(2, 2, 1)
plt.semilogx(side_numbers, pi_approximations, 'bo-', linewidth=2, markersize=4)
plt.axhline(y=math.pi, color='r', linestyle='--', label='真实π值')
plt.xlabel('正多边形的边数（对数尺度）')
plt.ylabel('π的近似值')
plt.title('用正多边形逼近π值')
plt.legend()
plt.grid(True, alpha=0.3)

# 子图2：误差分析
plt.subplot(2, 2, 2)
errors = [abs(approx - math.pi) for approx in pi_approximations]
plt.loglog(side_numbers, errors, 'ro-', linewidth=2, markersize=4)
plt.xlabel('正多边形的边数')
plt.ylabel('绝对误差')
plt.title('π近似值的误差（对数尺度）')
plt.grid(True, alpha=0.3)

# 子图3：绘制几个正多边形
plt.subplot(2, 2, 3)
example_sides = [4, 8, 16, 32]
for i, n in enumerate(example_sides):
    angles = np.linspace(0, 2*np.pi, n+1)
    x = np.cos(angles)
    y = np.sin(angles)
    
    # 调整位置，避免重叠
    offset_x = (i % 2) * 2.5
    offset_y = (i // 2) * 2.5
    
    plt.plot(x + offset_x, y + offset_y, linewidth=2)
    plt.fill(x + offset_x, y + offset_y, alpha=0.3)
    plt.text(offset_x, offset_y - 1.5, f'{n}边形', ha='center')
    
plt.xlim(-1, 5)
plt.ylim(-3, 3)
plt.axis('equal')
plt.title('正多边形逼近圆形')
plt.axis('off')

# 子图4：使用无穷级数计算π
plt.subplot(2, 2, 4)
# 莱布尼茨公式: π/4 = 1 - 1/3 + 1/5 - 1/7 + ...
terms = range(1, 1001)
leibniz_approximations = []
partial_sum = 0

for i, n in enumerate(terms):
    term = 1 / (2*n - 1) * (-1)**(n-1)
    partial_sum += term
    leibniz_approximations.append(4 * partial_sum)

plt.plot(terms, leibniz_approximations, 'g-', linewidth=1)
plt.axhline(y=math.pi, color='r', linestyle='--', label='真实π值')
plt.xlabel('级数项数')
plt.ylabel('π的近似值')
plt.title('莱布尼茨级数逼近π')
plt.legend()
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# 输出关键信息
print("π的几种计算方法:")
print(f"正1024边形逼近: {pi_approximations[-1]:.10f}")
print(f"真实π值: {math.pi:.10f}")
print(f"绝对误差: {abs(pi_approximations[-1] - math.pi):.10f}")

# 展示一些著名的π公式
print("\n著名的π公式:")
print("1. 莱布尼茨公式: π/4 = 1 - 1/3 + 1/5 - 1/7 + ...")
print("2. 欧拉公式: π²/6 = 1 + 1/2² + 1/3² + 1/4² + ...")